{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "456a591a-6383-45cf-ac3e-cca3014edf6b",
   "metadata": {},
   "source": [
    "# Introducing quantum functions with Quantum Monte Carlo Integration\n",
    "\n",
    "In this tutorial we introduce how to write custom quantum functions with Classiq, and subsequently use them for more complex functions/algorithms. This will be illustrated on a specific use-case of Quantum Monte Carlo Integration (QMCI). The example below demonstrates how we can exploit various concepts of modeling quantum algorithms with Classiq when building our own  functions."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "38184f42-a77b-4370-8e42-0224e711c5e0",
   "metadata": {},
   "source": [
    "## QMCI\n",
    "\n",
    "We start with a brief introduction to the quantum algorithm treated in this tutorial.\n",
    "\n",
    "Monte Carlo integration refers to estimating expectation values of a function $f(x)$, where $x$ is a random variable drawn from some known distribution $p$:\n",
    "\n",
    "\\begin{equation}\n",
    "\\tag{1}\n",
    "E_{p}(x) = \\int f(x)p(x) dx.\n",
    "\\end{equation}\n",
    "Such evaluations appear in the context of option-pricing or credit risk-analysis.\n",
    "\n",
    "The basic idea of QMCI assumes that we have a quantum function $A$, which, for a given $f$ and $p$, loads the following state of $n+1$ qubits:\n",
    "\\begin{align}\n",
    "\\tag{2}\n",
    "A|0\\rangle_n|0\\rangle = \\sum^{2^n-1}_{i=0} \\sqrt{f_i} \\sqrt{p_i}|i\\rangle_n|1\\rangle + \\sum^{2^n-1}_{i=0} \\sqrt{1-f_i} \\sqrt{p_i}|i\\rangle_n|0\\rangle = \\sqrt{a}|\\psi_1\\rangle+\\sqrt{1-a^2}|\\psi_0\\rangle,\n",
    "\\end{align}\n",
    "where it is understood that the first $2^n$ states represent a discretized space of $x$, and that $0\\leq f(x)\\leq 1$.\n",
    "Then, by applying Amplitude Estimation (AE) algorithm for the \"good-state\" $|\\psi_1 \\rangle$, we can estimate its amplitude\n",
    "$$\n",
    "a = \\sum^{2^n-1}_{i=0} f_i p_i.\n",
    "$$\n",
    "\n",
    "The QMCI algorithm can be separated into two parts:\n",
    "1) Constructing a Grover operator for the specific problem--- this will be done here almost from scratch.\n",
    "2) Applying AE algorithm based on the Grover operator [[1](#AE)]--- this will be done by calling Classiq's Quantum Phase Estimation (QPE) function.\n",
    "\n",
    "### Specific use-case for the tutorial\n",
    "\n",
    "For simplicity we will consider a simple use-case. We take a probability distribution on the integers\n",
    "$$\n",
    "\\tag{3}\n",
    "p_i = \\frac{i}{\\mathcal{N}} \\text{ for } i\\in \\{0,\\dots 2^3-1\\},\n",
    "$$\n",
    "where $\\mathcal{N}$ is a normalization constant, and we would like to evaluate the expectation value of the function\n",
    "$$\n",
    "\\tag{4}\n",
    "f(x) = \\sin^2(0.25x+0.2).\n",
    "$$\n",
    "Therefore, the value we want to evaluate is:\n",
    "$$\n",
    "a= \\frac{1}{\\mathcal{N}} \\sum^7_{k=0} \\sin^2(0.25k+0.2) k \\approx 0.834.\n",
    "$$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c810e0d5-6fda-4868-aab9-ff036ff8974e",
   "metadata": {},
   "source": [
    "## 1. Building the corresponding Grover Operator \n",
    "\n",
    "### Quantum Functions\n",
    "\n",
    "The following example will demonstrate how to define QMOD functions by writing a Python function decorated with the `@qfunc` decorator.\n",
    "The typical workflow for defining a quantum function:\n",
    "1. Specifying the function signature: The `@qfunc` decorator relies on Python's type-hint mechanism to extract the signature of the QMOD function from the argument list of the Python function.\n",
    "2. Specifying the function body: A function decorated with `@qfunc` is executed by the Python interpreter to construct the body of the QMOD function. Inside it, you can do one of the following:\n",
    "    - Call other `@qfuncs` to insert the corresponding quantum function calls into the body of the resulting QMOD function\n",
    "    - Introduce local quantum variables, by instantiating a quantum type\n",
    "    - Use arithmetic and in-place assignment operators to insert special quantum statements into the function\n",
    "    "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d259adad-9b69-4602-932b-97d98b546503",
   "metadata": {},
   "source": [
    "We can start with relevant imports"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "9f6fb018",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:57.062159Z",
     "iopub.status.busy": "2024-05-07T14:33:57.061654Z",
     "iopub.status.idle": "2024-05-07T14:33:59.810044Z",
     "shell.execute_reply": "2024-05-07T14:33:59.809432Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "from classiq import (\n",
    "    Constraints,\n",
    "    H,\n",
    "    Output,\n",
    "    Pauli,\n",
    "    QArray,\n",
    "    QBit,\n",
    "    QNum,\n",
    "    U,\n",
    "    X,\n",
    "    Z,\n",
    "    allocate,\n",
    "    allocate_num,\n",
    "    bind,\n",
    "    control,\n",
    "    create_model,\n",
    "    execute,\n",
    "    inplace_prepare_state,\n",
    "    invert,\n",
    "    linear_pauli_rotations,\n",
    "    qfunc,\n",
    "    qpe,\n",
    "    set_constraints,\n",
    "    show,\n",
    "    synthesize,\n",
    "    within_apply,\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c2be12ee-3d17-49df-a69f-efab41b60b29",
   "metadata": {},
   "source": [
    "### Grover operator for QMCI\n",
    "\n",
    "The Grover operator suitable for QMCI is defined as follows:\n",
    "$$\n",
    "Q\\equiv - S_{\\psi_1} A^{\\dagger} S_0 A,\n",
    "$$\n",
    "with $S_0$ and $S_{\\psi_1}$ being reflection operators around the zero state $|0\\rangle_n|0\\rangle$ and the good-state $|\\psi_1\\rangle$, respectively, and the function $A$ is defined in Eq. ([2](#mjx-eqn-2)).\n",
    "\n",
    "In subsections (1.1)-(1.3) below we build each of the quantum sub-functions, and then in subsection (1.4) we combine them to define a complete Grover operator. On the way we introduce several concepts of functional modeling which allow Classiq's Synthesis Engine to reach better optimized circuits. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a2c31065-077a-475a-ba06-af9b10a396d5",
   "metadata": {},
   "source": [
    "#### 1.1) The state loading $A$ function\n",
    "\n",
    "We start with constructing the $A$ operator in Eq. ([2](#mjx-eqn-2)). We define a quantum function and give it the name `state_loading`"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f9d562d6-0e6b-47ff-a130-1cd243ebdc61",
   "metadata": {},
   "source": [
    "The function's signature declares two arguments: \n",
    "1. A quantum register `io` declared as `QArray[QBit]` (an array of qubits with an unspecified size): will be used to represent the discretization of space\n",
    "2. A quantum register `ind` of size 1 declared as `QBit` to indicate the good state. "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5231c34a-89d9-433a-a85d-56517475f7f3",
   "metadata": {},
   "source": [
    "Next, we construct the logic flow of the `state_loading` function. \n",
    "The function body consists of 2 quantum function calls: `load_probabilities` followed by `amplitude_loading`\n",
    "\n",
    "- As can be seen from Eq. ([2](#mjx-eqn-2)), the `load_probabilities` function is constructed using Classiq's `inplace_prepare_state` function call on $n=3$ qubits with probabilities $p_i$ \n",
    "- The `amplitude_loading` body consists of a function call to Classiq's `linear_pauli_rotations`. The `linear_pauli_rotations` is used to load the amplitude of the function $ f(x) = sin^2(0.25 x + 0.2) $.\n",
    "\n",
    "    *Note: the amplitude should be $sin$ so the probability would be $sin^2$.*\n",
    "\n",
    "    The function uses an auxiliary qubit that is utilized so that the desired probability will reflect on the auxiliary qubit if it is in the `|1>` state.\n",
    "\n",
    "    We will use the function with the Pauli Y matrix and enter the appropriate slope and offset to achieve the right parameters.\n",
    "\n",
    "\n",
    "We will define the probabilities according to our specific problem described by Eqs. ([3](#mjx-eqn-3)-[4](#mjx-eqn-4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "253b8e94-b5a1-4fb7-b368-df2cd84af899",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:59.814636Z",
     "iopub.status.busy": "2024-05-07T14:33:59.813279Z",
     "iopub.status.idle": "2024-05-07T14:33:59.820653Z",
     "shell.execute_reply": "2024-05-07T14:33:59.820148Z"
    }
   },
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "sp_num_qubits = 3\n",
    "probabilities = np.linspace(0, 1, 2**sp_num_qubits) / sum(\n",
    "    np.linspace(0, 1, 2**sp_num_qubits)\n",
    ")\n",
    "\n",
    "\n",
    "slope = 0.5\n",
    "offset = 0.4\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def load_probabilities(state: QArray[QBit]):\n",
    "    inplace_prepare_state(probabilities.tolist(), 0, state)\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def amplitude_loading(io: QArray[QBit], ind: QBit):\n",
    "    linear_pauli_rotations(\n",
    "        bases=[Pauli.Y.value], slopes=[slope], offsets=[offset], x=io, q=ind\n",
    "    )\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def state_loading(io: QArray[QBit], ind: QBit):\n",
    "    load_probabilities(io)\n",
    "    amplitude_loading(io=io, ind=ind)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d06ba0e3-bbac-45d4-8ff5-46158b4038c8",
   "metadata": {},
   "source": [
    "To examine our function we define a quantum `main` function from which we can build a model, synthesize and view the quantum program created:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "cbfde910",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:33:59.824338Z",
     "iopub.status.busy": "2024-05-07T14:33:59.823433Z",
     "iopub.status.idle": "2024-05-07T14:34:02.413088Z",
     "shell.execute_reply": "2024-05-07T14:34:02.412394Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening: https://platform.classiq.io/circuit/34ad642f-d5bb-4768-adce-74bbac142f64?version=0.41.0.dev39%2B79c8fd0855\n"
     ]
    }
   ],
   "source": [
    "@qfunc\n",
    "def main(res: Output[QArray[QBit]], ind: Output[QBit]):\n",
    "    allocate(sp_num_qubits, res)\n",
    "    allocate(1, ind)\n",
    "    state_loading(res, ind)\n",
    "\n",
    "\n",
    "model = create_model(main)\n",
    "qprog = synthesize(model)\n",
    "show(qprog)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "59b38acb-9ca9-4cfd-b87a-4208c75c63ca",
   "metadata": {},
   "source": [
    "#### 1.2) $S_{\\psi_1}$ function - The good state oracle\n",
    "\n",
    "The next quantum function we define is the one which reflects around the good state: any $n+1$ state in which the `ind` register is at state $|1\\rangle$. This function can be simply constructed with a ZGate on the `ind` register. \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c965cf0b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:02.415594Z",
     "iopub.status.busy": "2024-05-07T14:34:02.415241Z",
     "iopub.status.idle": "2024-05-07T14:34:02.418415Z",
     "shell.execute_reply": "2024-05-07T14:34:02.417842Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "@qfunc\n",
    "def good_state_oracle(ind: QBit):\n",
    "    Z(ind)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fcc22b6c-8c2d-4ac9-ba63-c66416d40af9",
   "metadata": {},
   "source": [
    "#### 1.3) $S_{0}$ function - The Grover Diffuser\n",
    "\n",
    "In order to implement the Grover Diffuser we aim to perform a controlled-Z operation on the $|0>^n$ state.\n",
    "\n",
    "We can define a `zero_oracle` quantum function with the `io` and `ind` registers as its arguments. \n",
    "\n",
    "The `within_apply` operator takes two function arguments - compute and action, and invokes the sequence compute(), action(), and invert(compute()). Quantum objects that are allocated and prepared by compute are subsequently uncomputed and released.\n",
    "\n",
    "The `control` condition is a logical expression over a quantum variable. Currently, expressions are restricted to the form `<var> == <classical-expression>`, where both `<var>` and `<classical-expression>` are integer types."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "a32c9acb-34f3-42db-9d31-a7722634065a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:02.420863Z",
     "iopub.status.busy": "2024-05-07T14:34:02.420432Z",
     "iopub.status.idle": "2024-05-07T14:34:02.424131Z",
     "shell.execute_reply": "2024-05-07T14:34:02.423524Z"
    }
   },
   "outputs": [],
   "source": [
    "@qfunc\n",
    "def prepare_minus(q: QBit):\n",
    "    X(q)\n",
    "    H(q)\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def zero_oracle(x: QNum, ind: QBit):\n",
    "    within_apply(lambda: prepare_minus(ind), lambda: control(x == 0, lambda: X(ind)))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a8a9636f-0007-4ca8-98d5-6a1ce7002820",
   "metadata": {},
   "source": [
    "One can verify that:\n",
    "\\begin{eqnarray}\n",
    "|00\\dots0\\rangle \\xrightarrow[{\\rm ctrl(-Z)(target=q_0, ctrl=q_1\\dots q_n)}]{} -|00\\dots0\\rangle, \\\\\n",
    "|10\\dots0\\rangle \\xrightarrow[{\\rm ctrl(-Z)(target=q_0, ctrl=q_1\\dots q_n)}]{} |10\\dots0\\rangle, \\\\\n",
    "|11\\dots0\\rangle \\xrightarrow[{\\rm ctrl(-Z)(target=q_0, ctrl=q_1\\dots q_n)}]{} |11\\dots0\\rangle,\\\\\n",
    "|11\\dots1\\rangle \\xrightarrow[{\\rm ctrl(-Z)(target=q_0, ctrl=q_1\\dots q_n)}]{} |11\\dots1\\rangle,\n",
    "\\end{eqnarray}\n",
    "which is exactly the functionality we want.\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "52d45da1-8090-4e60-beed-9e4b3c57d929",
   "metadata": {},
   "source": [
    "#### 1.4) $Q$ function - The Grover operator\n",
    "\n",
    "We can now define a complete Grover operator $Q\\equiv -S_{\\psi_1} A^{\\dagger} S_0 A$. We will do this in a single code block that will call the following:\n",
    "1. The good state oracle (`good_state_oracle`)\n",
    "2. THe inverse of the state preparation (`state_loading`)\n",
    "3. The Diffuser (`zero_oracle`)\n",
    "4. The state preparation (`state_loading`)\n",
    " \n",
    "*Note:*\n",
    "- *Stages 2-4 are implemented by utilizing the `within_apply` operator*  \n",
    "- *We add a global phase of -1 to the full operator by using the atomic gate level function `U`*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "e0d94502",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:02.426640Z",
     "iopub.status.busy": "2024-05-07T14:34:02.426192Z",
     "iopub.status.idle": "2024-05-07T14:34:02.430281Z",
     "shell.execute_reply": "2024-05-07T14:34:02.429727Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "@qfunc\n",
    "def my_grover_operator(state: QArray[QBit]):\n",
    "    io = QArray[QBit](\"io\", length=state.len - 1)\n",
    "    ind = QBit(\"ind\")\n",
    "    bind(state, [ind, io])\n",
    "    good_state_oracle(ind=ind)\n",
    "    within_apply(\n",
    "        lambda: invert(lambda: state_loading(io=io, ind=ind)),\n",
    "        lambda: zero_oracle(io, ind),\n",
    "    )\n",
    "    U(0, 0, 0, np.pi, ind)\n",
    "    bind([ind, io], state)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0f4ffdde-0c92-436a-a28c-65cf843162de",
   "metadata": {},
   "source": [
    "##### Let us look at the `my_grover_operator` function we created"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a8cc707b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:02.432855Z",
     "iopub.status.busy": "2024-05-07T14:34:02.432319Z",
     "iopub.status.idle": "2024-05-07T14:34:05.796461Z",
     "shell.execute_reply": "2024-05-07T14:34:05.795768Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening: https://platform.classiq.io/circuit/e0a2e845-a21b-4c68-9d37-ae49d43ede11?version=0.41.0.dev39%2B79c8fd0855\n"
     ]
    }
   ],
   "source": [
    "@qfunc\n",
    "def main(state: Output[QArray[QBit]]):\n",
    "    io = QArray[QBit](\"io\")\n",
    "    ind = QBit(\"ind\")\n",
    "    allocate(sp_num_qubits, io)\n",
    "    allocate(1, ind)\n",
    "    bind([ind, io], state)\n",
    "    my_grover_operator(state)\n",
    "\n",
    "\n",
    "model = create_model(main)\n",
    "qprog = synthesize(model)\n",
    "show(qprog)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "11d58c71-9eff-420b-91fa-79d7ae0c886c",
   "metadata": {},
   "source": [
    "## 2. Applying Amplitude Estimation (AE) with Quantum Phase Estimation (QPE)\n",
    "\n",
    "Below we apply a basic AE algorithm which is based on QPE. The idea behind this Algorithm is the following:\n",
    "\n",
    "The state $A|0\\rangle_n|0\\rangle$ is spanned by two eigenvectors of our Grover operator $Q$, with the two corresponding eigenvalues\n",
    "\\begin{equation}\n",
    "\\tag{5}\n",
    "\\lambda_{\\pm}=\\exp\\left(\\pm i2\\pi \\theta \\right), \\qquad \\sin^2 \\left(\\pi \\theta\\right)\\equiv a.\n",
    "\\end{equation}\n",
    "Therefore, if we apply a QPE on $A|0\\rangle_n|0\\rangle$ we will have these two eigenvalues encoded in the QPE register, however, both give the value of $a$, so there is no ambiguity here."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "225566be-8c41-4d7a-abc6-ef3bb83a885b",
   "metadata": {},
   "source": [
    "To find $a$ we are going to build a simple quantum model: we apply $A$ on a quantum register of size $n+1$ initialized to zero, and then apply Classiq's QPE with the `my_grover_operator` we defined."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e0605069-5062-4f01-92f8-a6b599c7e4bd",
   "metadata": {},
   "source": [
    "Below is the `main` function from which we can build our model and synthesize it. In particular, we define the output register `phase` as `QNum` to hold the phase register output of the QPE. We choose a QPE with phase register of size 3, governing the accuracy of our Phase-, and thus Amplitude-, Estimation. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "144eeaf7-419a-4b03-962b-ef0ae09561d3",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:05.799288Z",
     "iopub.status.busy": "2024-05-07T14:34:05.798776Z",
     "iopub.status.idle": "2024-05-07T14:34:48.860729Z",
     "shell.execute_reply": "2024-05-07T14:34:48.859972Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Opening: https://platform.classiq.io/circuit/6ac9f51e-f111-4e96-ba45-975b333c0418?version=0.41.0.dev39%2B79c8fd0855\n"
     ]
    }
   ],
   "source": [
    "n_qpe = 3\n",
    "\n",
    "\n",
    "@qfunc\n",
    "def main(phase: Output[QNum]):\n",
    "    io = QArray[QBit](\"io\")\n",
    "    ind = QBit(\"ind\")\n",
    "    allocate(sp_num_qubits, io)\n",
    "    allocate(1, ind)\n",
    "    state_loading(io=io, ind=ind)\n",
    "    state = QArray[QBit](\"state\")\n",
    "    bind([ind, io], state)\n",
    "    allocate_num(n_qpe, False, n_qpe, phase)\n",
    "    qpe(unitary=lambda: my_grover_operator(state=state), phase=phase)\n",
    "    bind(state, [ind, io])\n",
    "\n",
    "\n",
    "model = create_model(main)\n",
    "model = set_constraints(model, Constraints(max_width=9))\n",
    "qprog = synthesize(model)\n",
    "show(qprog)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "14f3bf9f-4740-4849-896d-b9cb0dd064cb",
   "metadata": {},
   "source": [
    "We can simply export our model to a `.qmod` file:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "c49a283e-375a-442f-88bf-2ede31f5e829",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:48.865431Z",
     "iopub.status.busy": "2024-05-07T14:34:48.864235Z",
     "iopub.status.idle": "2024-05-07T14:34:48.890152Z",
     "shell.execute_reply": "2024-05-07T14:34:48.889531Z"
    }
   },
   "outputs": [],
   "source": [
    "from classiq import write_qmod\n",
    "\n",
    "write_qmod(model, \"qmc_user_defined\", decimal_precision=10)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94b452a3-7a47-440d-9c9a-bf88c9f5d3fd",
   "metadata": {},
   "source": [
    "### Finally, we execute the circuit and measure the approximated amplitude\n",
    "\n",
    "We start with a simple execution on a simulator"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "b22096f2-4e9c-4e22-8eec-2e1092760a36",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:48.893027Z",
     "iopub.status.busy": "2024-05-07T14:34:48.892580Z",
     "iopub.status.idle": "2024-05-07T14:34:52.072486Z",
     "shell.execute_reply": "2024-05-07T14:34:52.071814Z"
    }
   },
   "outputs": [],
   "source": [
    "res = execute(qprog).result()[0].value"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f3227fbf-15a4-4034-9623-62f9cc386335",
   "metadata": {},
   "source": [
    "We identify $|\\lambda_0,\\lambda_1\\dots \\lambda_{m-1}\\rangle_m=\\frac{1}{2^m}\\sum^{m-1}_{i=0}\\lambda_i 2^i$, whose mapping can be done as follows:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "cbfd0b33-7448-4fd3-843b-c74b09d47c8d",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:52.075231Z",
     "iopub.status.busy": "2024-05-07T14:34:52.074876Z",
     "iopub.status.idle": "2024-05-07T14:34:52.078087Z",
     "shell.execute_reply": "2024-05-07T14:34:52.077494Z"
    },
    "tags": []
   },
   "outputs": [],
   "source": [
    "## mapping between register string to phases\n",
    "phases_counts = dict(\n",
    "    (sampled_state.state[\"phase\"], sampled_state.shots)\n",
    "    for sampled_state in res.parsed_counts\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cee12720-1205-40d6-970f-eb36e76911ad",
   "metadata": {},
   "source": [
    "Plotting the resulting histogram we see two phase values with high probability (however, both corresponds to the same amplitude $a$)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "d6a77c5d-c684-40e7-97ef-ec73ce659535",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:52.080517Z",
     "iopub.status.busy": "2024-05-07T14:34:52.080096Z",
     "iopub.status.idle": "2024-05-07T14:34:52.228611Z",
     "shell.execute_reply": "2024-05-07T14:34:52.227932Z"
    },
    "tags": []
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "phase with max probability:  0.625\n"
     ]
    },
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAigAAAGlCAYAAADQyw0eAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuNSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/xnp5ZAAAACXBIWXMAAA9hAAAPYQGoP6dpAAAf00lEQVR4nO3de3BU9fnH8U9CSMJtNwZhF4QAnaohyk2oZL3NT4ykNFossVORQWwZHTEwQgqFWAyC1iC1YnFAOshFqxRlxstAuBjjAG2zXIxljFDwhiY2bIKlZAXLJpD9/WHZuoLVhZDzbHy/Zs6Me87Z7HP8xubdze4mIRwOhwUAAGBIotMDAAAAfBWBAgAAzCFQAACAOQQKAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHOSnB7gbDQ3N6u2tlZdunRRQkKC0+MAAIBvIRwO67PPPlPPnj2VmPi/nyOJy0Cpra1V7969nR4DAACchZqaGvXq1et/nhOXgdKlSxdJX1ygy+VyeBoAAPBtBINB9e7dO/Jz/H+Jy0A59Wsdl8tFoAAAEGe+zcszeJEsAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzCFQAACAOQQKAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYE6S0wMAAOJT31mlTo/Q4j6an+f0CPgPnkEBAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzCFQAACAOQQKAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzIkpUB588EElJCREbZmZmZHjx48fV0FBgbp27arOnTsrPz9fdXV1UV+jurpaeXl56tixo7p3764ZM2boxIkTLXM1AACgTUiK9Q6XXXaZXn/99f9+gaT/folp06aptLRUa9euldvt1uTJkzVmzBj99a9/lSSdPHlSeXl58nq9qqio0MGDB3XHHXeoffv2euSRR1rgcgAAQFsQc6AkJSXJ6/Wetr+hoUHLly/X6tWrNWLECEnSypUr1b9/f23fvl3Z2dl67bXXtHfvXr3++uvyeDwaPHiwHnroIc2cOVMPPvigkpOTz/2KAABA3Iv5NSjvvfeeevbsqe9973saN26cqqurJUmVlZVqampSTk5O5NzMzExlZGTI7/dLkvx+vwYMGCCPxxM5Jzc3V8FgUHv27DnXawEAAG1ETM+gDB8+XKtWrdKll16qgwcPau7cubr22mv1zjvvKBAIKDk5WWlpaVH38Xg8CgQCkqRAIBAVJ6eOnzr2dUKhkEKhUOR2MBiMZWwAABBnYgqUUaNGRf554MCBGj58uPr06aMXX3xRHTp0aPHhTikpKdHcuXPP29cHAAC2nNPbjNPS0nTJJZfo/fffl9frVWNjo44cORJ1Tl1dXeQ1K16v97R39Zy6fabXtZxSVFSkhoaGyFZTU3MuYwMAAOPOKVCOHj2qDz74QD169NDQoUPVvn17lZeXR47v379f1dXV8vl8kiSfz6eqqirV19dHzikrK5PL5VJWVtbXPk5KSopcLlfUBgAA2q6YfsUzffp03XzzzerTp49qa2s1Z84ctWvXTmPHjpXb7dbEiRNVWFio9PR0uVwuTZkyRT6fT9nZ2ZKkkSNHKisrS+PHj9eCBQsUCAQ0e/ZsFRQUKCUl5bxcIAAAiD8xBconn3yisWPH6p///Ke6deuma665Rtu3b1e3bt0kSQsXLlRiYqLy8/MVCoWUm5urJUuWRO7frl07rV+/XpMmTZLP51OnTp00YcIEzZs3r2WvCgAAxLWEcDgcdnqIWAWDQbndbjU0NPDrHgBwSN9ZpU6P0OI+mp/n9AhtWiw/v/lbPAAAwBwCBQAAmEOgAAAAcwgUAABgDoECAADMIVAAAIA5BAoAADCHQAEAAOYQKAAAwBwCBQAAmEOgAAAAcwgUAABgDoECAADMIVAAAIA5BAoAADCHQAEAAOYQKAAAwBwCBQAAmEOgAAAAcwgUAABgTpLTAwCIH31nlTo9Qov7aH6e0yMAOAOeQQEAAOYQKAAAwBwCBQAAmEOgAAAAcwgUAABgDoECAADMIVAAAIA5BAoAADCHQAEAAOYQKAAAwBwCBQAAmEOgAAAAcwgUAABgDoECAADMIVAAAIA5BAoAADCHQAEAAOYQKAAAwBwCBQAAmEOgAAAAcwgUAABgDoECAADMIVAAAIA5BAoAADCHQAEAAOYQKAAAwBwCBQAAmEOgAAAAcwgUAABgDoECAADMIVAAAIA5BAoAADCHQAEAAOYQKAAAwBwCBQAAmHNOgTJ//nwlJCRo6tSpkX3Hjx9XQUGBunbtqs6dOys/P191dXVR96uurlZeXp46duyo7t27a8aMGTpx4sS5jAIAANqQsw6UXbt26Q9/+IMGDhwYtX/atGlat26d1q5dq61bt6q2tlZjxoyJHD958qTy8vLU2NioiooKPfPMM1q1apWKi4vP/ioAAECbclaBcvToUY0bN07Lli3TBRdcENnf0NCg5cuX6/HHH9eIESM0dOhQrVy5UhUVFdq+fbsk6bXXXtPevXv13HPPafDgwRo1apQeeughLV68WI2NjS1zVQAAIK6dVaAUFBQoLy9POTk5UfsrKyvV1NQUtT8zM1MZGRny+/2SJL/frwEDBsjj8UTOyc3NVTAY1J49e874eKFQSMFgMGoDAABtV1Ksd1izZo3eeust7dq167RjgUBAycnJSktLi9rv8XgUCAQi53w5Tk4dP3XsTEpKSjR37txYRwUAAHEqpmdQampqdN999+n5559Xamrq+ZrpNEVFRWpoaIhsNTU1rfbYAACg9cUUKJWVlaqvr9cVV1yhpKQkJSUlaevWrVq0aJGSkpLk8XjU2NioI0eORN2vrq5OXq9XkuT1ek97V8+p26fO+aqUlBS5XK6oDQAAtF0xBcoNN9ygqqoq7d69O7INGzZM48aNi/xz+/btVV5eHrnP/v37VV1dLZ/PJ0ny+XyqqqpSfX195JyysjK5XC5lZWW10GUBAIB4FtNrULp06aLLL788al+nTp3UtWvXyP6JEyeqsLBQ6enpcrlcmjJlinw+n7KzsyVJI0eOVFZWlsaPH68FCxYoEAho9uzZKigoUEpKSgtdFgAAiGcxv0j2myxcuFCJiYnKz89XKBRSbm6ulixZEjnerl07rV+/XpMmTZLP51OnTp00YcIEzZs3r6VHAQAAceqcA2XLli1Rt1NTU7V48WItXrz4a+/Tp08fbdiw4VwfGgAAtFH8LR4AAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYE1OgPPXUUxo4cKBcLpdcLpd8Pp82btwYOX78+HEVFBSoa9eu6ty5s/Lz81VXVxf1Naqrq5WXl6eOHTuqe/fumjFjhk6cONEyVwMAANqEmAKlV69emj9/viorK/Xmm29qxIgRGj16tPbs2SNJmjZtmtatW6e1a9dq69atqq2t1ZgxYyL3P3nypPLy8tTY2KiKigo988wzWrVqlYqLi1v2qgAAQFxLCIfD4XP5Aunp6frtb3+rW2+9Vd26ddPq1at16623SpL27dun/v37y+/3Kzs7Wxs3btRNN92k2tpaeTweSdLSpUs1c+ZMHTp0SMnJyd/qMYPBoNxutxoaGuRyuc5lfAAx6Dur1OkRWtxH8/OcHiFu8f2AWMXy8/usX4Ny8uRJrVmzRseOHZPP51NlZaWampqUk5MTOSczM1MZGRny+/2SJL/frwEDBkTiRJJyc3MVDAYjz8IAAAAkxXqHqqoq+Xw+HT9+XJ07d9bLL7+srKws7d69W8nJyUpLS4s63+PxKBAISJICgUBUnJw6furY1wmFQgqFQpHbwWAw1rEBAEAcifkZlEsvvVS7d+/Wjh07NGnSJE2YMEF79+49H7NFlJSUyO12R7bevXuf18cDAADOijlQkpOT9f3vf19Dhw5VSUmJBg0apN///vfyer1qbGzUkSNHos6vq6uT1+uVJHm93tPe1XPq9qlzzqSoqEgNDQ2RraamJtaxAQBAHDnnz0Fpbm5WKBTS0KFD1b59e5WXl0eO7d+/X9XV1fL5fJIkn8+nqqoq1dfXR84pKyuTy+VSVlbW1z5GSkpK5K3NpzYAANB2xfQalKKiIo0aNUoZGRn67LPPtHr1am3ZskWbN2+W2+3WxIkTVVhYqPT0dLlcLk2ZMkU+n0/Z2dmSpJEjRyorK0vjx4/XggULFAgENHv2bBUUFCglJeW8XCAAAIg/MQVKfX297rjjDh08eFBut1sDBw7U5s2bdeONN0qSFi5cqMTEROXn5ysUCik3N1dLliyJ3L9du3Zav369Jk2aJJ/Pp06dOmnChAmaN29ey14VAACIa+f8OShO4HNQAGfwuRf4Mr4fEKtW+RwUAACA84VAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkxBUpJSYl+8IMfqEuXLurevbtuueUW7d+/P+qc48ePq6CgQF27dlXnzp2Vn5+vurq6qHOqq6uVl5enjh07qnv37poxY4ZOnDhx7lcDAADahJgCZevWrSooKND27dtVVlampqYmjRw5UseOHYucM23aNK1bt05r167V1q1bVVtbqzFjxkSOnzx5Unl5eWpsbFRFRYWeeeYZrVq1SsXFxS13VQAAIK4lhMPh8Nne+dChQ+revbu2bt2q6667Tg0NDerWrZtWr16tW2+9VZK0b98+9e/fX36/X9nZ2dq4caNuuukm1dbWyuPxSJKWLl2qmTNn6tChQ0pOTv7Gxw0Gg3K73WpoaJDL5Trb8QHEqO+sUqdHaHEfzc9zeoS4xfcDYhXLz+9zeg1KQ0ODJCk9PV2SVFlZqaamJuXk5ETOyczMVEZGhvx+vyTJ7/drwIABkTiRpNzcXAWDQe3Zs+eMjxMKhRQMBqM2AADQdp11oDQ3N2vq1Km6+uqrdfnll0uSAoGAkpOTlZaWFnWux+NRIBCInPPlODl1/NSxMykpKZHb7Y5svXv3PtuxAQBAHDjrQCkoKNA777yjNWvWtOQ8Z1RUVKSGhobIVlNTc94fEwAAOCfpbO40efJkrV+/Xtu2bVOvXr0i+71erxobG3XkyJGoZ1Hq6urk9Xoj5+zcuTPq6516l8+pc74qJSVFKSkpZzMqAACIQzE9gxIOhzV58mS9/PLLeuONN9SvX7+o40OHDlX79u1VXl4e2bd//35VV1fL5/NJknw+n6qqqlRfXx85p6ysTC6XS1lZWedyLQAAoI2I6RmUgoICrV69Wq+++qq6dOkSec2I2+1Whw4d5Ha7NXHiRBUWFio9PV0ul0tTpkyRz+dTdna2JGnkyJHKysrS+PHjtWDBAgUCAc2ePVsFBQU8SwIAACTFGChPPfWUJOn//u//ovavXLlSd955pyRp4cKFSkxMVH5+vkKhkHJzc7VkyZLIue3atdP69es1adIk+Xw+derUSRMmTNC8efPO7UoAAECbEVOgfJuPTElNTdXixYu1ePHirz2nT58+2rBhQywPDQAAvkP4WzwAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzCFQAACAOQQKAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzCFQAACAOQQKAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzCFQAACAOQQKAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzCFQAACAOQQKAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzCFQAACAOQQKAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzCFQAACAOQQKAAAwh0ABAADmECgAAMAcAgUAAJhDoAAAAHMIFAAAYA6BAgAAzCFQAACAOQQKAAAwh0ABAADmxBwo27Zt080336yePXsqISFBr7zyStTxcDis4uJi9ejRQx06dFBOTo7ee++9qHMOHz6scePGyeVyKS0tTRMnTtTRo0fP6UIAAEDbEXOgHDt2TIMGDdLixYvPeHzBggVatGiRli5dqh07dqhTp07Kzc3V8ePHI+eMGzdOe/bsUVlZmdavX69t27bp7rvvPvurAAAAbUpSrHcYNWqURo0adcZj4XBYTzzxhGbPnq3Ro0dLkp599ll5PB698soruu222/T3v/9dmzZt0q5duzRs2DBJ0pNPPqkf/ehHeuyxx9SzZ89zuBwAANAWtOhrUA4cOKBAIKCcnJzIPrfbreHDh8vv90uS/H6/0tLSInEiSTk5OUpMTNSOHTvO+HVDoZCCwWDUBgAA2q4WDZRAICBJ8ng8Ufs9Hk/kWCAQUPfu3aOOJyUlKT09PXLOV5WUlMjtdke23r17t+TYAADAmLh4F09RUZEaGhoiW01NjdMjAQCA86hFA8Xr9UqS6urqovbX1dVFjnm9XtXX10cdP3HihA4fPhw556tSUlLkcrmiNgAA0Ha1aKD069dPXq9X5eXlkX3BYFA7duyQz+eTJPl8Ph05ckSVlZWRc9544w01Nzdr+PDhLTkOAACIUzG/i+fo0aN6//33I7cPHDig3bt3Kz09XRkZGZo6daoefvhhXXzxxerXr58eeOAB9ezZU7fccoskqX///vrhD3+ou+66S0uXLlVTU5MmT56s2267jXfwAAAASWcRKG+++aauv/76yO3CwkJJ0oQJE7Rq1Sr96le/0rFjx3T33XfryJEjuuaaa7Rp0yalpqZG7vP8889r8uTJuuGGG5SYmKj8/HwtWrSoBS4HAAC0BQnhcDjs9BCxCgaDcrvdamho4PUoQCvqO6vU6RFa3Efz85weIW7x/YBYxfLzOy7exQMAAL5bCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAAABzCBQAAGAOgQIAAMwhUAAAgDkECgAAMIdAAQAA5hAoAADAHEcDZfHixerbt69SU1M1fPhw7dy508lxAACAEY4FygsvvKDCwkLNmTNHb731lgYNGqTc3FzV19c7NRIAADAiyakHfvzxx3XXXXfp5z//uSRp6dKlKi0t1YoVKzRr1iynxgKAb9R3VqnTI7S4j+bnOT1CXON7ouU5EiiNjY2qrKxUUVFRZF9iYqJycnLk9/tPOz8UCikUCkVuNzQ0SJKCweB5me/yOZvPy9d10jtzc50eIW7x/fBfzaHPW3gS553N/47w7+EL/Hv4L/5dxPY1w+HwN58cdsA//vGPsKRwRUVF1P4ZM2aEr7zyytPOnzNnTlgSGxsbGxsbWxvYampqvrEVHPsVTyyKiopUWFgYud3c3KzDhw+ra9euSkhIcHCysxcMBtW7d2/V1NTI5XI5PQ6+BusUH1in+MA6xY/ztVbhcFifffaZevbs+Y3nOhIoF154odq1a6e6urqo/XV1dfJ6vaedn5KSopSUlKh9aWlp53PEVuNyufgPNQ6wTvGBdYoPrFP8OB9r5Xa7v9V5jryLJzk5WUOHDlV5eXlkX3Nzs8rLy+Xz+ZwYCQAAGOLYr3gKCws1YcIEDRs2TFdeeaWeeOIJHTt2LPKuHgAA8N3lWKD87Gc/06FDh1RcXKxAIKDBgwdr06ZN8ng8To3UqlJSUjRnzpzTfnUFW1in+MA6xQfWKX5YWKuEcPjbvNcHAACg9fC3eAAAgDkECgAAMIdAAQAA5hAoAADAHAIFAACYQ6AAaBMOHDigEydOOD0GvgFrFD+cfpMvgdJK9u7dq3vvvVdDhgxRjx491KNHDw0ZMkT33nuv9u7d6/R4+I+DBw/queee04YNG9TY2Bh17NixY5o3b55Dk+GbXHrppXrvvfecHgP/sWnTJlVVVUn64pPCH3roIV100UVKSUlRr169NH/+fMd/AEIKhUKaPn26rrvuOj366KOSpIcfflidO3dWly5ddPvtt5+Xv2r8bfA5KK1g48aNuuWWW3TFFVcoNzc38mF0dXV1KisrU2VlpV599VXl5uY6POl3265duzRy5Eg1NzerqalJF110kV555RVddtllkr5Yr549e+rkyZMOT/rdNmbMmDPuf/XVVzVixAh16dJFkvTSSy+15lj4iszMTC1btkzXXnutSkpK9Lvf/U6//vWv1b9/f+3fv18lJSWaNm2aZs6c6fSo32mFhYV64YUXNHbsWG3YsEHXX3+91q9fr0ceeUSJiYkqLi7WqFGjtGjRolafjUBpBYMGDdLo0aO/9v99P/jgg3rppZf09ttvt/Jk+LIbb7xRvXv31tNPP61jx45p5syZevHFF1VWVqYhQ4YQKEYkJibquuuuU79+/aL2P/vss/rxj38c+UOiK1eudGA6nJKamqp3331XGRkZGjBggIqLi/XTn/40cry0tFRTp07lWS+HZWRkaMWKFcrJydGHH36oiy++WC+99JJGjx4tSSorK9Ndd92ljz76qPWHC+O8S01NDe/bt+9rj+/bty+cmpraihPhTC644ILw/v37o/aVlJSEL7jggvDOnTvDgUAgnJiY6NB0OOVPf/pTuFevXuEVK1ZE7U9KSgrv2bPHoanwVT169Aj7/f5wOBwOezye8FtvvRV1/N133w136NDBidHwJR06dAh//PHHkdvt27cPv/POO5HbBw4cCHfs2NGJ0cK8BqUV9O3bV6WlpV97vLS0VH369GnFifB1jh8/HnV71qxZuv/++zVy5EhVVFQ4NBW+7LbbbtOf//xnLV++XPn5+frXv/7l9Eg4g5/85Cf6zW9+o5MnT2r06NFasmRJ1GtOnnzySQ0ePNi5ASHpi2dQ/H6/pC9+zZ2QkKCdO3dGju/YsUMXXXSRI7M59scCv0vmzZun22+/XVu2bFFOTk7Ua1DKy8u1adMmrV692uEpcfnll6uiokIDBw6M2j99+nQ1Nzdr7NixDk2Gr+rbt6+2bdumuXPnatCgQVq2bJkSEhKcHgtf8sgjjygnJ0eZmZny+Xxau3atysrKdMkll+j999/X4cOHtXnzZqfH/M675557dOedd+rpp59WZWWlHnvsMd1///3at2+fEhMT9dRTT+mXv/ylI7PxGpRWUlFRoUWLFsnv9ysQCEiSvF6vfD6f7rvvPvl8PocnxNNPP62tW7fqj3/84xmPP/roo1q6dKkOHDjQypPhf/nLX/6iO+64Qx9//LGqqqqUlZXl9Ej4j6amJi1fvlzr1q3Thx9+qObmZvXo0UNXX321Jk2apF69ejk9IiStXr1afr9fV111lcaOHastW7aouLhYn3/+uW6++WY98MADSkxs/V+4ECgA4t7Ro0f1wQcfqH///kpOTnZ6HAAtgEABAADm8CJZA+6//3794he/cHoMfAPWKT6wTvGBdYoPTq4TL5I14JNPPtEnn3zi9Bj4BqxTfGCd4gPrFB+cXCd+xQMAAMzhGZRW8umnn2rFihWnvYvnqquu0p133qlu3bo5PCEk1ilesE7xgXWKD1bXiWdQWsGuXbuUm5urjh07nvFzUD7//HNt3rxZw4YNc3jS7zbWKT6wTvGBdYoPlteJQGkF2dnZGjRokJYuXXrah0mFw2Hdc889evvttyOf5gdnsE7xgXWKD6xTfLC8TgRKK+jQoYP+9re/KTMz84zH9+3bpyFDhujf//53K0+GL2Od4gPrFB9Yp/hgeZ14m3Er8Hq9UX/b4Kt27twZeVoNzmGd4gPrFB9Yp/hgeZ14kWwrmD59uu6++25VVlbqhhtuOO13fMuWLdNjjz3m8JRgneID6xQfWKf4YHqdWvePJ393rVmzJjx8+PBwUlJSOCEhIZyQkBBOSkoKDx8+PPzCCy84PR7+g3WKD6xTfGCd4oPVdeI1KK2sqalJn376qSTpwgsvVPv27R2eCGfCOsUH1ik+sE7xwdo6ESgAAMAcXiQLAADMIVAAAIA5BAoAADCHQAEAAOYQKAAAwBwCBQAAmEOgAAAAcwgUAABgzv8DsfO0Yct68nQAAAAASUVORK5CYII=",
      "text/plain": [
       "<Figure size 640x480 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.bar(phases_counts.keys(), phases_counts.values(), width=0.1)\n",
    "plt.xticks(rotation=90)\n",
    "print(\"phase with max probability: \", max(phases_counts, key=phases_counts.get))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e75fe2d0-3e27-48e6-b8ee-0b9a33b7eb12",
   "metadata": {},
   "source": [
    "Recall the relation in Eq. ([5](#mjx-eqn-5)), we can read the amplitude $a$ from the phase with max probability, and compare to the expected amplitude:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "7cb7d1a6-1923-4149-8152-c03459c8c26b",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2024-05-07T14:34:52.231315Z",
     "iopub.status.busy": "2024-05-07T14:34:52.230780Z",
     "iopub.status.idle": "2024-05-07T14:34:52.235565Z",
     "shell.execute_reply": "2024-05-07T14:34:52.234939Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "measured amplitude:  0.8535533905932737\n",
      "exact amplitude:  0.8338393824876795\n"
     ]
    }
   ],
   "source": [
    "print(\n",
    "    \"measured amplitude: \",\n",
    "    np.sin(np.pi * max(phases_counts, key=phases_counts.get)) ** 2,\n",
    ")\n",
    "print(\n",
    "    \"exact amplitude: \",\n",
    "    sum(np.sin(0.5 * n / 2 + 0.4 / 2) ** 2 * probabilities[n] for n in range(2**3)),\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66648b44-71d9-47d8-9756-3faea9474745",
   "metadata": {},
   "source": [
    "## References\n",
    "\n",
    "<a name='AE'>[1]</a>: [Brassard, G., Hoyer, P., Mosca, M., & Tapp, A. (2002). Quantum Amplitude Amplification and Estimation. Contemporary Mathematics, 305, 53-74.](https://arxiv.org/abs/quant-ph/0005055)\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
